package core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import agency.Sales;
import basic.QuerySet;
import common.Bank;
import common.Bram;
import common.Card;
import common.Gbpp;
import common.Intercept;
import common.Ip;
import common.Notify;
import common.Risk;
import common.Sequence;
import common.Service;
import common.Servlet;
import common.Validate;
import dict.BcDict;
import dict.CommonDict;
import dict.TransactionDict;
import dicts.CountryDict;
import dicts.EmailDict;
import dicts.GlobalDict;
import dicts.PaymentDict;
import entities.TBank;
import entities.TBc;
import entities.TBin;
import entities.TCard;
import entities.TCs;
import entities.TCurrency;
import entities.TMerchant;
import entities.TMs;
import entities.TReplace;
import entities.TRisk;
import entities.TSm;
import entities.TSubject;
import entities.TTransaction;
import entities.TWebsite;
import interfaces.IBankService;
import interfaces.IBcService;
import interfaces.IBinService;
import interfaces.IBlackaddrService;
import interfaces.IBlackbinService;
import interfaces.IBlackcardService;
import interfaces.IBlackcountryService;
import interfaces.IBlackemailService;
import interfaces.IBlackfingerService;
import interfaces.IBlackipService;
import interfaces.IBlacknameService;
import interfaces.IBlackphoneService;
import interfaces.IBlackstateService;
import interfaces.IBlackwebsiteService;
import interfaces.ICardService;
import interfaces.ICsService;
import interfaces.ICurrencyService;
import interfaces.IInterceptService;
import interfaces.IMerchantService;
import interfaces.IMsService;
import interfaces.IReplaceService;
import interfaces.IRiskService;
import interfaces.ISmService;
import interfaces.ISubjectService;
import interfaces.ITransactionService;
import interfaces.IWebsiteService;
import interfaces.IWhitecardService;
import interfaces.IWhiteipService;
import net.sf.json.JSONObject;
import util.LogUtil;
import util.ParameterUtil ;
import utils.AesUtil;
import utils.DateUtil;
import utils.DigestUtil;
import utils.NumberUtil;
import utils.StringUtil;

public class Entrance extends Servlet {

	private static final long serialVersionUID = 1L;

	public void process(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println(DateUtil.format(new Date(), DateUtil.DATETIME) + " | 交易网关");
		Long topTime = System.currentTimeMillis();

		// 初始化service
		ICurrencyService currencyService = (ICurrencyService) Service.create(ICurrencyService.class);
		ISubjectService subjectService = (ISubjectService) Service.create(ISubjectService.class);
		IMerchantService merchantService = (IMerchantService) Service.create(IMerchantService.class);
		ICardService cardService = (ICardService) Service.create(ICardService.class);
		IBinService binService = (IBinService) Service.create(IBinService.class);
		IBankService bankService = (IBankService) Service.create(IBankService.class);
		IWebsiteService websiteService = (IWebsiteService) Service.create(IWebsiteService.class);
		IReplaceService replaceService = (IReplaceService) Service.create(IReplaceService.class);
		ITransactionService transactionService = (ITransactionService) Service.create(ITransactionService.class);
		IInterceptService interceptService = (IInterceptService) Service.create(IInterceptService.class);
		IRiskService riskService = (IRiskService) Service.create(IRiskService.class);
		IBcService bcService = (IBcService) Service.create(IBcService.class);
		ICsService csService = (ICsService) Service.create(ICsService.class);
		ISmService smService = (ISmService) Service.create(ISmService.class);
		IMsService msService = (IMsService) Service.create(IMsService.class);

		IBlackbinService blackbinService = (IBlackbinService) Service.create(IBlackbinService.class);
		IBlackcardService blackcardService = (IBlackcardService) Service.create(IBlackcardService.class);
		IBlackcountryService blackcountryService = (IBlackcountryService) Service.create(IBlackcountryService.class);
		IBlackfingerService blackfingerService = (IBlackfingerService) Service.create(IBlackfingerService.class);
		IBlackipService blackipService = (IBlackipService) Service.create(IBlackipService.class);
		IBlackstateService blackstateService = (IBlackstateService) Service.create(IBlackstateService.class);
		IBlackaddrService blackaddrService = (IBlackaddrService) Service.create(IBlackaddrService.class);
		IBlackemailService blackemailService = (IBlackemailService) Service.create(IBlackemailService.class);
		IBlacknameService blacknameService = (IBlacknameService) Service.create(IBlacknameService.class);
		IBlackphoneService blackphoneService = (IBlackphoneService) Service.create(IBlackphoneService.class);
		IBlackwebsiteService blackwebsiteService = (IBlackwebsiteService) Service.create(IBlackwebsiteService.class);
		IWhiteipService whiteipService = (IWhiteipService) Service.create(IWhiteipService.class);
		IWhitecardService whitecardService = (IWhitecardService) Service.create(IWhitecardService.class);

		QuerySet<Object> querySet = new QuerySet<Object>();
		Map<String, Object> paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
		JSONObject jsonResult = new JSONObject();

		// 初始化bean和属性
		TBank bank = new TBank();
		TSubject subject = new TSubject();
		TMerchant merchant = new TMerchant();
		TWebsite website = new TWebsite();
		TReplace replace = new TReplace();
		TCurrency currency = new TCurrency();
		TCard card = new TCard();
		TTransaction transaction = new TTransaction();
		TBin bin = new TBin();
		TBc bc = new TBc();
		TCs cs = new TCs();
		TSm sm = new TSm();
		TMs ms = new TMs();

		// 验证系统
		if (GlobalDict.LINUX.equalsIgnoreCase(System.getProperty("os.name")) && !CommonDict.HOST.equals(request.getServerName())) {
			response.getWriter().print(Validate.result(TransactionDict.ILLAGEL_ACCESS, TransactionDict.MESSAGES.get(TransactionDict.ILLAGEL_ACCESS)));
			return;
		}

		// 校验参数 ( 名称,值,校验模式,边界 )
		List<Object[]> parameterList = Collections.synchronizedList(new ArrayList<Object[]>());
		parameterList.add(new Object[] { "version", request.getParameter("version"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "no", request.getParameter("no"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 5, 6 });
		parameterList.add(new Object[] { "order", request.getParameter("order"), Validate.NOTEMPTY | Validate.CHARNUMBER | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "site", request.getParameter("site"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH | Validate.NOHTTPHEADER, 0, 100 });
		parameterList.add(new Object[] { "cur", request.getParameter("cur"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "loc", request.getParameter("loc"), Validate.NOTEMPTY | Validate.ISNUMBER | Validate.EXCEEDNUMBER, 0, Integer.MAX_VALUE });
		parameterList.add(new Object[] { "notify", request.getParameter("notify"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH | Validate.HTTPHEADER, 0, 500 });
		parameterList.add(new Object[] { "product", request.getParameter("product"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 500 });
		parameterList.add(new Object[] { "signature", request.getParameter("signature"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 500 });
		parameterList.add(new Object[] { "number", request.getParameter("number"), Validate.EXCEEDLENGTH, 0, 100 });
		parameterList.add(new Object[] { "expire", request.getParameter("expire"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "cvv", request.getParameter("cvv"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "ip", request.getParameter("ip"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 200 });
		parameterList.add(new Object[] { "os", request.getParameter("os"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "browser", request.getParameter("browser"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "finger", request.getParameter("finger"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "locale", request.getParameter("locale"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "timing", request.getParameter("timing"), Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "cfname", request.getParameter("cfname"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "clname", request.getParameter("clname"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "cphone", request.getParameter("cphone"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "cemail", request.getParameter("cemail"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH | Validate.EMAILFORMAT, 0, 100 });
		parameterList.add(new Object[] { "ccountry", request.getParameter("ccountry"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "cstate", request.getParameter("cstate"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "ccity", request.getParameter("ccity"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "caddr", request.getParameter("caddr"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 200 });
		parameterList.add(new Object[] { "czip", request.getParameter("czip"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "hfname", request.getParameter("hfname"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "hlname", request.getParameter("hlname"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "hphone", request.getParameter("hphone"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "hemail", request.getParameter("hemail"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH | Validate.EMAILFORMAT, 0, 100 });
		parameterList.add(new Object[] { "hcountry", request.getParameter("hcountry"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "hstate", request.getParameter("hstate"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "hcity", request.getParameter("hcity"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });
		parameterList.add(new Object[] { "haddr", request.getParameter("haddr"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 200 });
		parameterList.add(new Object[] { "hzip", request.getParameter("hzip"), Validate.NOTEMPTY | Validate.EXCEEDLENGTH, 0, 50 });

		JSONObject validateResult = Validate.validate(parameterList);
		LogUtil.enter(Validate.summary(parameterList));

		if (!StringUtil.isEmpty(validateResult)) {
			System.out.println ( validateResult.toString() ) ;
			response.getWriter().print(validateResult.toString());
			return;
		}

		if (!request.getParameter("version").equals(GlobalDict.VERSION)) {
			response.getWriter().print(Validate.result(TransactionDict.VERSION_ERROR, TransactionDict.MESSAGES.get(TransactionDict.VERSION_ERROR)));
			return;
		}

		// 格式化非必须参数
		card.setCrdIp(Ip.getCommonIp(request.getParameter("ip")));
		card.setCrdOs(StringUtil.isEmpty(request.getParameter("os")) ? CommonDict.UNKNOWN : request.getParameter("os"));
		card.setCrdBrowser(StringUtil.isEmpty(request.getParameter("browser")) ? CommonDict.UNKNOWN : request.getParameter("browser"));
		card.setCrdFinger(StringUtil.isEmpty(request.getParameter("finger")) ? CommonDict.UNKNOWN : request.getParameter("finger"));
		card.setCrdLocale(StringUtil.isEmpty(request.getParameter("locale")) ? CommonDict.UNKNOWN : request.getParameter("locale"));
		card.setCrdTiming(StringUtil.isEmpty(request.getParameter("timing")) ? CommonDict.UNKNOWN : request.getParameter("timing"));
		card.setCrdCode(Ip.getCountryCode(card.getCrdIp()));
		card.setCrdCfname(request.getParameter("cfname").replaceAll ( "-" , "" ));
		card.setCrdClname(request.getParameter("clname").replaceAll ( "-" , "" ));
		card.setCrdCphone(request.getParameter("cphone").replaceAll ( "-" , "" ));
		card.setCrdCemail(request.getParameter("cemail").replaceAll ( "-" , "" ).toLowerCase());
		card.setCrdCcountry(CountryDict.shortName(request.getParameter("ccountry")));
		card.setCrdCstate(request.getParameter("cstate").replaceAll ( "-" , "" ));
		card.setCrdCcity(request.getParameter("ccity").replaceAll ( "-" , "" ));
		card.setCrdCaddr(StringUtil.concise(request.getParameter("caddr")));
		card.setCrdCzip(request.getParameter("czip").replaceAll ( "-" , "" ));
		card.setCrdHfname(request.getParameter("hfname").replaceAll ( "-" , "" ));
		card.setCrdHlname(request.getParameter("hlname").replaceAll ( "-" , "" ));
		card.setCrdHphone(request.getParameter("hphone").replaceAll ( "-" , "" ));
		card.setCrdHemail(request.getParameter("hemail").replaceAll ( "-" , "" ).toLowerCase());
		card.setCrdHcountry(CountryDict.shortName(request.getParameter("hcountry")));
		card.setCrdHstate(request.getParameter("hstate").replaceAll ( "-" , "" ));
		card.setCrdHcity(request.getParameter("hcity").replaceAll ( "-" , "" ));
		card.setCrdHaddr(StringUtil.concise(request.getParameter("haddr")));
		card.setCrdHzip(request.getParameter("hzip").replaceAll ( "-" , "" ));

		transaction.setTxnOrder(request.getParameter("order"));
		transaction.setTxnSite(request.getParameter("site").toLowerCase());
		transaction.setTxnCur(request.getParameter("cur"));
		transaction.setTxnLoc(new Double(request.getParameter("loc")));
		transaction.setTxnNotify(request.getParameter("notify"));
		transaction.setTxnProduct(request.getParameter("product"));
		transaction.setTxnRefund("0");
		transaction.setTxnRefuse("0");
		transaction.setTxnFreeze("0");
		transaction.setTxnLogic("0");
		transaction.setTxnSettle("0");
		transaction.setTxnVisible("0");
		transaction.setTxnDanger("0");

		// 校验子账户存在和状态
		try {
			subject = subjectService.fetch(request.getParameter("no"));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.SUBJECT_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.SUBJECT_FETCH_EXCEPTION)));
			return;
		}

		if (subject == null) {
			response.getWriter().print(Validate.result(TransactionDict.SUBJECT_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.SUBJECT_NOT_EXIST)));
			return;
		}

		if (!subject.getSubState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.SUBJECT_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.SUBJECT_STATUS_EXCEPTION)));
			return;
		}

		// 交易商户存在和状态
		try {
			merchant = merchantService.fetch(subject.getSubNo().substring(0, 4));
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_FETCH_EXCEPTION)));
			return;
		}

		if (merchant == null) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_NOT_EXIST, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_NOT_EXIST)));
			return;
		}

		if (!merchant.getMerState().equals("1")) {
			response.getWriter().print(Validate.result(TransactionDict.MERCHANT_STATUS_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.MERCHANT_STATUS_EXCEPTION)));
			return;
		}

		// 交易网站存在和状态
		try {
			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
			paramMap.put("webNo", StringUtil.split(subject.getSubNo()));
			paramMap.put("webAddress", transaction.getTxnSite());
			website = websiteService.single(paramMap);
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.WEBSITE_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.WEBSITE_FETCH_EXCEPTION)));
			return;
		}

		// 网站不存在则新增网站
		try {
			if (website == null) {
				website = new TWebsite();
				website.setWebNo(subject.getSubNo());
				website.setWebAddress(transaction.getTxnSite());
				website.setWebSign(StringUtil.number(6));
				website.setWebDescript("暂无");
				website.setWebValidity(GlobalDict.YEAR.doubleValue());
				website.setWebState("0");
				website.setWebDate(new Date());
				website.setWebVstate("0");
				website.setWebVdate(new Date(0L));
				website = websiteService.persist(website);
			}
		} catch (Exception e) {
			response.getWriter().print(Validate.result(TransactionDict.WEBSITE_PERSIST_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.WEBSITE_PERSIST_EXCEPTION)));
			return;
		}

		System.out.println("[" + Thread.currentThread().getName() + "]" + "verify complated ");

		//////////////////////// ---从这里开始记录拦截交易记录,并使用商户子账户网站字符串组合作为锁进行线程保护---//////////////////////////////////////

		synchronized ((merchant.getMerNo() + subject.getSubNo() + website.getWebNo()).intern()) {

			// 网站已经审核并且没有通过
			if (!website.getWebState().equals("1") && website.getWebVstate().equals("1")) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "网站未通过审核[" + website.getWebAddress() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.WEBSITE_FORBIDDEN, TransactionDict.MESSAGES.get(TransactionDict.WEBSITE_FORBIDDEN)));
				return;
			}

			// 币种存在状态
			try {
				currency = currencyService.fetch(transaction.getTxnCur());
			} catch (Exception e) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "币种异常[" + transaction.getTxnCur() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CURRENCY_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CURRENCY_FETCH_EXCEPTION)));
				return;
			}

			// 币种不存在
			if (currency == null) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "币种不支持[" + transaction.getTxnCur() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.NO_SUPPORT_CURRENCY, TransactionDict.MESSAGES.get(TransactionDict.NO_SUPPORT_CURRENCY)));
				return;
			}

			// 计算交易金额
			try {
				transaction.setTxnNo(website.getWebNo());
				transaction.setTxnName("[" + merchant.getMerNo() + "]" + transaction.getTxnOrder());
				transaction.setMerNo(merchant.getMerNo());
				transaction.setTxnRate(currency.getCurRate());
				transaction.setTxnAmount(NumberUtil.mul(transaction.getTxnLoc(), transaction.getTxnRate()));
				transaction.setTxnRemain(transaction.getTxnAmount());
			} catch (Exception e) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "金额计算异常[" + e.getMessage() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CALCULATE_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CALCULATE_EXCEPTION)));
				return;
			}

			// 校验金额范围是否商户允许
			if (transaction.getTxnAmount() < new Double(merchant.getMerEnd()) || transaction.getTxnAmount() > new Double(merchant.getMerTop())) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "金额超限[" + transaction.getTxnAmount() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.AMOUNT_EXCEEDED, TransactionDict.MESSAGES.get(TransactionDict.AMOUNT_EXCEEDED)));
				return;
			}

			// 校验数字签名
			if (!DigestUtil.sha256(subject.getSubNo() + transaction.getTxnOrder() + transaction.getTxnCur() + NumberUtil.transfer(transaction.getTxnLoc()) + subject.getSubKey()).equalsIgnoreCase(request.getParameter("signature"))) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "数字签名错[" + request.getParameter("signature") + "]"));
				response.getWriter().print(Validate.result(TransactionDict.SIGNATURE_INCORRECT, TransactionDict.MESSAGES.get(TransactionDict.SIGNATURE_INCORRECT)));
				return;
			}

			// 解密卡信息
			try {
				card.setCrdNumber(AesUtil.AES_Decrypt(DigestUtil.md5(subject.getSubKey()), request.getParameter("number")));
				card.setCrdExpire(AesUtil.AES_Decrypt(DigestUtil.md5(subject.getSubKey()), request.getParameter("expire")));
				card.setCrdCvv(AesUtil.AES_Decrypt(DigestUtil.md5(subject.getSubKey()), request.getParameter("cvv")));
			} catch (Exception e) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(),
						"卡信息还原异常[" + request.getParameter("number") + "|" + request.getParameter("expire") + "|" + request.getParameter("cvv") + "]"));
				response.getWriter().print(Validate.result(TransactionDict.INFORMATION_DECRYPT_ERROR, TransactionDict.MESSAGES.get(TransactionDict.INFORMATION_DECRYPT_ERROR)));
				return;
			}

			// 校验卡信息是否合法
			if (!Card.legalCard(card.getCrdNumber())) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "卡号信息不符合编码标准[" + card.getCrdNumber() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CARD_NUMBER_FORMAT_ERROR, TransactionDict.MESSAGES.get(TransactionDict.CARD_NUMBER_FORMAT_ERROR)));
				return;
			}

			if (!Card.legalExpire(card.getCrdExpire())) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "有效期信息不符合编码标准或超期[" + card.getCrdExpire() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CARD_EXPIRE_FORMAT_ERROR, TransactionDict.MESSAGES.get(TransactionDict.CARD_EXPIRE_FORMAT_ERROR)));
				return;
			}

			if (!Card.legalCvv(card.getCrdCvv())) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "卡CVV信息不符合编码标准[" + card.getCrdCvv() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CARD_CVV_FORMAT_ERROR, TransactionDict.MESSAGES.get(TransactionDict.CARD_CVV_FORMAT_ERROR)));
				return;
			}

			// 校验商户是否开通该类型卡通道,没开通直接返回
			if (!Card.isEffective(card.getCrdNumber(), merchant, Card.MASTER)) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "未开通此卡类型[" + Card.type(card.getCrdNumber()) + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CARD_NOT_ACCEPT, "[" + card.getCrdType() + "]" + TransactionDict.MESSAGES.get(TransactionDict.CARD_NOT_ACCEPT)));
				return;
			}

			// 获取卡bin
			try {
				bin = binService.fetch(Card.toBin(card.getCrdNumber()));
				card.setCrdBin ( ( ( bin == null ) ? CommonDict.UNCODE : bin.getBinCountry ( ) ) ) ;
				card.setCrdType(Card.type(card.getCrdNumber()));
				card.setCrdFake(Card.toFake(card.getCrdNumber()));
				card.setCrdNo(Card.build(card));
				transaction.setCrdNo(card.getCrdNo());
			} catch (Exception e) {
				e.printStackTrace ( );
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "卡信息处理异常[" + e.getMessage() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.CARD_TRANSFER_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.CARD_TRANSFER_EXCEPTION)));
				return;
			}

			// 静态风控 风险黑名单验证条件

			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
			paramMap.put("merNo", new String[] { merchant.getMerNo(), CommonDict.GLOBAL_MERCHANT });
			paramMap.put("bckIp", new String[] { card.getCrdIp() });
			paramMap.put("whtIp", new String[] { card.getCrdIp() });
			paramMap.put("bckCard", new String[] { card.getCrdNumber() });
			paramMap.put("whtCard", new String[] { card.getCrdNumber() });
			paramMap.put("bckBin", new String[] { Card.toBin(card.getCrdNumber()) });
			paramMap.put("bckFinger", new String[] { card.getCrdFinger() });
			paramMap.put("bckWebsite", new String[] { transaction.getTxnSite() });
			paramMap.put("bckCountry", new String[] { card.getCrdCcountry(), card.getCrdHcountry() });
			paramMap.put("bckState", new String[] { card.getCrdCstate(), card.getCrdHcountry() });
			paramMap.put("bckName", new String[] { card.getCrdCfname() + " " + card.getCrdClname(), card.getCrdHfname() + " " + card.getCrdHlname() });
			paramMap.put("bckEmail", new String[] { card.getCrdCemail(), card.getCrdHcountry() });
			paramMap.put("bckPhone", new String[] { card.getCrdCphone(), card.getCrdHphone() });
			paramMap.put("bckAddr", new String[] { card.getCrdCaddr(), card.getCrdHaddr() });

			if (!whiteipService.contain(paramMap) && blackipService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑IP名单[" + card.getCrdIp() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_IP, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_IP)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑IP名单");
			}
			if (!whitecardService.contain(paramMap) && blackcardService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑卡名单[" + card.getCrdNumber() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_CARD, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_CARD)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑卡名单");
			}
			if (blackbinService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑BIN名单[" + card.getCrdBin() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_BIN, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_BIN)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑卡BIN名单");
			}
			if (blackfingerService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑指纹名单[" + card.getCrdFinger() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_FINGER, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_FINGER)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑指纹名单");
			}
			if (blackwebsiteService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑网站名单[" + transaction.getTxnSite() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_WEBSITE, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_WEBSITE)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑网站名单");
			}
			if (blackcountryService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑国家名单[" + card.getCrdCcountry() + "|" + card.getCrdHcountry() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_COUNTRY, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_COUNTRY)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑国家名单");
			}
			if (blackstateService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑州/省名单[" + card.getCrdCstate() + "|" + card.getCrdHstate() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_STATE, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_STATE)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑州/省名单");
			}
			if (blackaddrService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑地址名单[" + card.getCrdCaddr() + "|" + card.getCrdHaddr() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_ADDR, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_ADDR)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑地址名单");
			}
			if (blackemailService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑邮箱名单[" + card.getCrdCemail() + "|" + card.getCrdHemail() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_EMAIL, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_EMAIL)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑邮箱名单");
			}
			if (blacknameService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(),
							"属于黑姓名名单[" + card.getCrdCfname() + " " + card.getCrdClname() + "|" + card.getCrdHfname() + " " + card.getCrdHlname() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_NAME, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_NAME)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑姓名名单");
			}
			if (blackphoneService.contain(paramMap)) {
				if (merchant.getMerRisking().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "属于黑电话名单[" + card.getCrdCphone() + "|" + card.getCrdHphone() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BLACK_PHONE, TransactionDict.MESSAGES.get(TransactionDict.RISK_BLACK_PHONE)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("属于黑电话名单");
			}

			// IP国家码和卡BIN国家码和收货国家码和账单国家码之间的比较
			if (!Ip.isSafeCountry(card.getCrdCode(), card.getCrdBin())) {
				if (merchant.getMerComparing().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "IP国家码和银行国家码不一致[" + card.getCrdCode() + "|" + card.getCrdBin() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_CARD_BIN, TransactionDict.MESSAGES.get(TransactionDict.RISK_CARD_BIN)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("IP国家码和银行国家码不一致");
			}
			if (!Ip.isSafeCountry(card.getCrdCode(), card.getCrdCcountry())) {
				if (merchant.getMerComparing().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "IP国家码和收货国家码不一致[" + card.getCrdCode() + "|" + card.getCrdCcountry() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_CARD_CCOUNTRY, TransactionDict.MESSAGES.get(TransactionDict.RISK_CARD_CCOUNTRY)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("IP国家码和收货国家码不一致");
			}
			if (!Ip.isSafeCountry(card.getCrdCode(), card.getCrdHcountry())) {
				if (merchant.getMerComparing().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "IP国家码和账单国家码不一致[" + card.getCrdCode() + "|" + card.getCrdHcountry() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_CARD_HCOUNTRY, TransactionDict.MESSAGES.get(TransactionDict.RISK_CARD_HCOUNTRY)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("IP国家码和账单国家码不一致");
			}
			if (!Ip.isSafeCountry(card.getCrdBin(), card.getCrdCcountry())) {
				if (merchant.getMerComparing().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "银行国家码和收货国家码不一致[" + card.getCrdBin() + "|" + card.getCrdCcountry() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BIN_CCOUNTRY, TransactionDict.MESSAGES.get(TransactionDict.RISK_BIN_CCOUNTRY)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("银行国家码和收货国家码不一致");
			}
			if (!Ip.isSafeCountry(card.getCrdBin(), card.getCrdHcountry())) {
				if (merchant.getMerComparing().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "银行国家码和账单国家码不一致[" + card.getCrdBin() + "|" + card.getCrdHcountry() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_BIN_HCOUNTRY, TransactionDict.MESSAGES.get(TransactionDict.RISK_BIN_HCOUNTRY)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("银行国家码和账单国家码不一致");
			}
			if (!Ip.isSafeCountry(card.getCrdCcountry(), card.getCrdHcountry())) {
				if (merchant.getMerComparing().equals("1")) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "收货国家码和账单国家码不一致[" + card.getCrdCcountry() + "|" + card.getCrdHcountry() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.RISK_CCOUNTRY_HCOUNTRY, TransactionDict.MESSAGES.get(TransactionDict.RISK_CCOUNTRY_HCOUNTRY)));
					return;
				}
				transaction.setTxnDanger("1");
				transaction.setTxnRemark("收货国家码和账单国家码不一致");
			}

			// 商户交易笔数限制
			if (merchant.getMerCounting().equals("1")) {
				querySet = new QuerySet<Object>();
				paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
				paramMap.put("txnNo", StringUtil.split(merchant.getMerNo()));
				paramMap.put("txnState", "1");
				paramMap.put("txnDate", ParameterUtil.dateCombin ( new Date(), new Date() ));
				querySet.setPolymerizeInfo("txnAmount");
				querySet.setParamMap(paramMap);

				if (transactionService.record(paramMap) > merchant.getMerPer()) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "当日交易笔数超限[" + merchant.getMerPer() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.TOTAL_TIMES_LIMIT, TransactionDict.MESSAGES.get(TransactionDict.TOTAL_TIMES_LIMIT)));
					return;
				}
				if (transactionService.summary(querySet) > merchant.getMerSum()) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "当日交易金额超限[" + merchant.getMerSum() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.TOTAL_AMOUNT_LIMIT, TransactionDict.MESSAGES.get(TransactionDict.TOTAL_AMOUNT_LIMIT)));
					return;
				}
			}

			// 如果邮箱类型不允许则阻止
			if (EmailDict.EMAIL_SET.contains(StringUtil.removeStart(card.getCrdCemail(), CommonDict.SPLIT_EMAIL)) || EmailDict.EMAIL_SET.contains(StringUtil.removeStart(card.getCrdHemail(), CommonDict.SPLIT_EMAIL))) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(),
						"不合法的邮箱类型[" + StringUtil.removeStart(card.getCrdCemail(), CommonDict.SPLIT_EMAIL) + "|" + StringUtil.removeStart(card.getCrdHemail(), CommonDict.SPLIT_EMAIL) + "]"));
				response.getWriter().print(Validate.result(TransactionDict.EMAIL_INCORRECT, TransactionDict.MESSAGES.get(TransactionDict.EMAIL_INCORRECT)));
				return;
			}

			// GBPP
			if (Card.isVisa(card.getCrdNumber()) && Gbpp.isGbpp(card.getCrdIp(), card.getCrdOs(), card.getCrdBrowser())) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "持卡人信息符合gbpp检测范围[" + card.getCrdIp() + "|" + card.getCrdOs() + "|" + card.getCrdBrowser() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.GBPP_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.GBPP_EXCEPTION)));
				return;
			}

			// BRAM
			if (Card.isMaster(card.getCrdNumber()) && Bram.isBram(card.getCrdIp())) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "持卡人信息符合bram检测范围[" + card.getCrdIp() + "|" + card.getCrdOs() + "|" + card.getCrdBrowser() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.BRAM_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.BRAM_EXCEPTION)));
				return;
			}

			// 防重复提交
			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
			paramMap.put("txnNo", StringUtil.split(website.getWebNo()));
			paramMap.put("crdNo", StringUtil.split(card.getCrdNo()));
			paramMap.put("txnOrder", transaction.getTxnOrder());
			paramMap.put("txnCur", transaction.getTxnCur());
			paramMap.put("txnLoc", transaction.getTxnLoc());
			if (transactionService.contain(paramMap)) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(),
						"相同交易信息重复提交[" + website.getWebNo() + "|" + card.getCrdNo() + "|" + transaction.getTxnOrder() + "|" + transaction.getTxnCur() + "|" + transaction.getTxnLoc() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.REPEAT_SUBMIT, TransactionDict.MESSAGES.get(TransactionDict.REPEAT_SUBMIT)));
				return;
			}

			// 防同订单号重复付款
			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
			paramMap.put("txnNo", StringUtil.split(website.getWebNo()));
			paramMap.put("txnOrder", transaction.getTxnOrder());
			paramMap.put("txnState", "1");
			if (transactionService.contain(paramMap)) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "同订单号交易试图重复付款[" + website.getWebNo() + "|" + transaction.getTxnOrder() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.DUPLICATE_PAYMENT, TransactionDict.MESSAGES.get(TransactionDict.DUPLICATE_PAYMENT)));
				return;
			}

			// 防当天同IP重复付款
//			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
//			paramMap.put("txnNo", StringUtil.split(website.getWebNo()));
//			paramMap.put("crdIp", card.getCrdIp());
//			paramMap.put("txnState", "1");
//			paramMap.put("txnDate", new Date[] { new Date(), new Date() });
//			if (transactionService.possess(paramMap)) {
//				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "同IP持卡人当天重复付款[" + website.getWebNo() + "|" + card.getCrdIp() + "]"));
//				response.getWriter().print(Validate.result(TransactionDict.GLOBAL_IP_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.GLOBAL_IP_EXCEPTION)));
//				return;
//			}

			// 防当天同卡号重复付款
			if(!merchant.getMerNo ( ).equals ( "7777" )&&!merchant.getMerNo ( ).equals ( "8888" )){
				paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
				paramMap.put("txnNo", StringUtil.split(website.getWebNo()));
				paramMap.put("crdNumber", card.getCrdNumber());
				paramMap.put("txnState", "1");
				paramMap.put("txnDate", ParameterUtil.dateCombin ( new Date(), new Date() ));
				if (transactionService.possess(paramMap)) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "同一张卡当天重复付款[" + website.getWebNo() + "|" + card.getCrdNumber() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.GLOBAL_CARD_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.GLOBAL_CARD_EXCEPTION)));
					return;
				}

				// 防当天同邮箱重复付款
				paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
				paramMap.put("txnNo", StringUtil.split(website.getWebNo()));
				paramMap.put("crdCemail", card.getCrdCemail());
				paramMap.put("txnState", "1");
				paramMap.put("txnDate", ParameterUtil.dateCombin ( new Date(), new Date() ));
				if (transactionService.possess(paramMap)) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "同用户邮箱当天重复付款[" + website.getWebNo() + "|" + transaction.getTxnSite() + "]"));
					response.getWriter().print(Validate.result(TransactionDict.GLOBAL_CARD_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.GLOBAL_CARD_EXCEPTION)));
					return;
				}
			
			}

			System.out.println("[" + Thread.currentThread().getName() + "]" + "check complated ");

			querySet = new QuerySet<Object>();
			paramMap = Collections.synchronizedMap(new HashMap<String, Object>());
			paramMap.put("merNo", merchant.getMerNo());
			paramMap.put("rskState", "1");
			querySet.setParamMap(paramMap);
			List<TRisk> riskList = riskService.search(querySet).getResultList();
			for (TRisk risk : riskList) {
				// 符合风控规则
				if (new Risk().verify(risk, card, merchant.getMerNo(), subject.getSubNo(), website.getWebNo())) {
					if (risk.getRskPolicy().equals("阻止")) {
						interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "符合动态风控规则[" + risk.getRskRemark() + "]"));
						response.getWriter().print(Validate.result(risk.getRskCode(), risk.getRskMessage()));
						return;
					} else {
						transaction.setTxnDanger("1");
						transaction.setTxnRemark(risk.getRskRemark());
					}
				}
			}

			System.out.println("[" + Thread.currentThread().getName() + "]" + "risk complated");

			try {
				card.setCrdState("1");
				card.setCrdDate(new Date());
				card.setCrdExpire(AesUtil.AES_Encrypt(AesUtil.KEY, card.getCrdExpire()));
				card.setCrdCvv(AesUtil.AES_Encrypt(AesUtil.KEY, card.getCrdCvv()));
				card = cardService.persist(card);

				transaction.setTxnState("0");
				transaction.setTxnDate(new Date());
				transaction = transactionService.persist(transaction);
			} catch (Exception e) {
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "存储交易数据异常[" + e.getMessage() + "]"));
				response.getWriter().print(Validate.result(TransactionDict.TRANSACTION_PERSIST_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_PERSIST_EXCEPTION)));
				return;
			}

			System.out.println("[" + Thread.currentThread().getName() + "]" + transaction.getTxnName() + " stand by");

			// 得到对应卡种的通道对象
			bank = bankService.fetch(Card.toBank(card.getCrdNumber(), merchant, Card.MASTER));

			// // 如果通道开启伪站功能,则修改送往上游的网址
			// if (bank.getBnkFake().equals("1")) {
			// paramMap = Collections.synchronizedMap(new HashMap<String,
			// Object>());
			// paramMap.put("bnkNo", bank.getBnkNo());
			// replace = replaceService.dynamic(paramMap);
			// if (!StringUtil.isEmpty(replace)) {
			// transaction.setTxnSite(replace.getRepAddress());
			// }
			// }

			// 把交易送往主通道收单
			try {
				bc = new TBc();
				bc.setBcNo(Sequence.bcSequence());
				bc.setCrdNo(card.getCrdNo());
				bc.setBnkNo(bank.getBnkNo());
				bc.setTxnNo(transaction.getTxnNo());
				bc.setBcType(PaymentDict.BC_BLUSH);
				bc.setBcOrder(bc.getBcNo());
				bc.setBcCur(CommonDict.CUR);
				bc.setBcAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.add(new Double(1), Bank.markup(transaction.getTxnAmount(), bank) , 4)));
				bc.setBcMoney(bc.getBcAmount());
				bc.setBcState("0");
				bc.setBcDate(new Date());
				bc.setBcCstate("0");
				bc.setBcCdate(new Date(0L));
				((Sales) Class.forName("agency.sales." + StringUtil.upperHead(bank.getBnkNo().substring(0, 6).toLowerCase())).newInstance()).process(bc, transaction, bank, card);
				bcService.persist(bc);
			} catch (Exception e) {
				e.printStackTrace();
				interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "主通道入账上送异常"));
				response.getWriter().print(Validate.result(TransactionDict.AGENCY_FETCH_EXCEPTION, TransactionDict.MESSAGES.get(TransactionDict.AGENCY_FETCH_EXCEPTION)));
				return;
			}

			System.out.println("[" + Thread.currentThread().getName() + "]" + "master [" + bank.getBnkNo() + "] complated");

			// 主通道支付失败而且备通道属于开通状态
			if (!bc.getBcState().equals("1") && Card.isEffective(card.getCrdNumber(), merchant, Card.SLAVE)) {
				// 得到对应卡种的通道对象
				bank = bankService.fetch(Card.toBank(card.getCrdNumber(), merchant, Card.SLAVE));

				// // 如果通道开启伪站功能,则修改送往上游的网址
				// if (bank.getBnkFake().equals("1")) {
				// paramMap = Collections.synchronizedMap(new HashMap<String,
				// Object>());
				// paramMap.put("bnkNo", bank.getBnkNo());
				// replace = replaceService.dynamic(paramMap);
				// if (!StringUtil.isEmpty(replace)) {
				// transaction.setTxnSite(replace.getRepAddress());
				// }
				// }

				try {
					bc = new TBc();
					bc.setBcNo(Sequence.bcSequence());
					bc.setCrdNo(card.getCrdNo());
					bc.setBnkNo(bank.getBnkNo());
					bc.setTxnNo(transaction.getTxnNo());
					bc.setBcType(PaymentDict.BC_BLUSH);
					bc.setBcOrder(bc.getBcNo());
					bc.setBcCur(CommonDict.CUR);
					bc.setBcAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.add(new Double(1), Bank.markup(transaction.getTxnAmount(), bank) , 4)));
					bc.setBcMoney(bc.getBcAmount());
					bc.setBcState("0");
					bc.setBcDate(new Date());
					bc.setBcCstate("0");
					bc.setBcCdate(new Date(0L));
					((Sales) Class.forName("agency.sales." + StringUtil.upperHead(bank.getBnkNo().substring(0, 6).toLowerCase())).newInstance()).process(bc, transaction, bank, card);
					bcService.persist(bc);
				} catch (Exception e) {
					interceptService.persist(Intercept.intercept(website.getWebNo(), transaction.getTxnOrder(), transaction.getTxnSite(), "备通道入账上送异常[" + e.getMessage() + "]"));
					response.getWriter().print(Validate.result(BcDict.BC_PROCESS_EXCEPTION, BcDict.MESSAGES.get(BcDict.BC_PROCESS_EXCEPTION)));
					return;
				}

				System.out.println("[" + Thread.currentThread().getName() + "]" + "slave  [" + bank.getBnkNo() + "] complated");
			}

			// 提交上游处理完成后根据收单状态进行清结算
			if (bc.getBcState().equals("1")) {
				if (merchant.getMerShipping().equals("1")) {
					transaction.setTxnLogic("1");
				}
				transaction.setTxnState("1");
				transactionService.persist(transaction);

				cs.setCsNo(Sequence.csSequence());
				cs.setCrdNo(card.getCrdNo());
				cs.setTxnNo(transaction.getTxnNo());
				cs.setCsType(PaymentDict.CS_DEALAGE);
				cs.setCsAmount(transaction.getTxnAmount());
				cs.setCsState("1");
				cs.setCsDate(new Date());
				csService.persist(cs);

				cs.setCsNo(Sequence.csSequence());
				cs.setCrdNo(card.getCrdNo());
				cs.setTxnNo(transaction.getTxnNo());
				cs.setCsType(PaymentDict.CS_MARKUP);
				cs.setCsAmount(NumberUtil.sub(bc.getBcAmount(), transaction.getTxnAmount()));
				cs.setCsState("1");
				cs.setCsDate(new Date());
				csService.persist(cs);

				sm.setSmNo(Sequence.smSequence());
				sm.setMerNo(merchant.getMerNo());
				sm.setTxnNo(transaction.getTxnNo());
				sm.setSmType(PaymentDict.SM_THANSFER);
				sm.setSmAmount(transaction.getTxnAmount());
				sm.setSmState("1");
				sm.setSmDate(new Date());
				smService.persist(sm);

				ms.setMsNo(Sequence.msSequence());
				ms.setMerNo(merchant.getMerNo());
				ms.setTxnNo(transaction.getTxnNo());
				ms.setMsType(PaymentDict.MS_POUNDAGE);
				ms.setMsAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(Card.toPoundage(card.getCrdNumber(), merchant), new Double(100), 4)));
				ms.setMsState("1");
				ms.setMsDate(new Date());
				msService.persist(ms);

				ms.setMsNo(Sequence.msSequence());
				ms.setMerNo(merchant.getMerNo());
				ms.setTxnNo(transaction.getTxnNo());
				ms.setMsType(PaymentDict.MS_MORTGAGE);
				ms.setMsAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(Card.toMortgage(card.getCrdNumber(), merchant), new Double(100), 4)));
				ms.setMsState("1");
				ms.setMsDate(new Date());
				msService.persist(ms);

				sm.setSmNo(Sequence.smSequence());
				sm.setMerNo(merchant.getMerNo());
				sm.setTxnNo(transaction.getTxnNo());
				sm.setSmType(PaymentDict.SM_MORTGAGE);
				sm.setSmAmount(NumberUtil.mul(transaction.getTxnAmount(), NumberUtil.div(Card.toMortgage(card.getCrdNumber(), merchant), new Double(100), 4)));
				sm.setSmState("0");
				sm.setSmDate(new Date(new Date().getTime() + NumberUtil.mul(merchant.getMerReturn(), GlobalDict.DAY.doubleValue()).longValue()));
				smService.persist(sm);
			}

			Long endTime = System.currentTimeMillis();
			System.out.println("[" + Thread.currentThread().getName() + "]" + "transcation complated . time spend :" + NumberUtil.div(endTime.doubleValue() - topTime.doubleValue(), 1000D) + " sec");

			jsonResult.put("version", GlobalDict.VERSION);
			jsonResult.put("no", subject.getSubNo());
			jsonResult.put("transaction", transaction.getTxnNo());
			jsonResult.put("order", transaction.getTxnOrder());
			jsonResult.put("cur", transaction.getTxnCur());
			jsonResult.put("loc", NumberUtil.transfer(transaction.getTxnLoc()));
			jsonResult.put("rate", NumberUtil.transfer(transaction.getTxnRate(), 4));
			jsonResult.put("amount", NumberUtil.transfer(transaction.getTxnAmount()));
			jsonResult.put("issue", bank.getBnkBill());
			// 如果交易失败
			if (transaction.getTxnState().equals("0")) {
				jsonResult.put("code", bc.getBcCode());
				jsonResult.put("message", bc.getBcMessage());
				jsonResult.put("signature", DigestUtil.sha256(GlobalDict.VERSION+subject.getSubNo() + transaction.getTxnOrder() + NumberUtil.transfer(transaction.getTxnAmount ( )) +jsonResult.getString ( "code" )+ subject.getSubKey()));
				// 设置了失败通知
				if (merchant.getMerNotifying().equals("1")) {
					Notify.assembly(transaction.getTxnNotify(), jsonResult);
					LogUtil.notify ( Notify.redirect ( transaction.getTxnNotify(), jsonResult ) );
				}
				response.getWriter().print(jsonResult.toString());
				return;
			}
			// 如果交易成功
			jsonResult.put("code", TransactionDict.TRANSACTION_SUCCESS);
			jsonResult.put("message", TransactionDict.MESSAGES.get(TransactionDict.TRANSACTION_SUCCESS));
			jsonResult.put("signature", DigestUtil.sha256(GlobalDict.VERSION+subject.getSubNo() + transaction.getTxnOrder() + NumberUtil.transfer(transaction.getTxnAmount ( )) +jsonResult.getString ( "code" )+ subject.getSubKey()));
			Notify.assembly(transaction.getTxnNotify(), jsonResult);
			LogUtil.notify ( Notify.redirect ( transaction.getTxnNotify(), jsonResult ) );
			response.getWriter().print(jsonResult.toString());
			return;
		}
	}
}
